// -*-c++-*-

#ifndef _TABLE_HPP_
#define _TABLE_HPP_

#include <map>
#include <string>

#include <protocol.hpp>
#include <stringable.hpp>

#include "table_schema.hpp"
#include "tablet.hpp"

namespace xbase {
	
	class table {
	public:
		typedef boost::shared_ptr<table> pointer;

		typedef __gnu_cxx::hash_map<std::string, tablet::pointer> tablet_map;

	public:
		table(const std::string &p_table_name);

		~table() {}

		tablet::pointer get_tablet(const std::string &p_tablet_name) const;
		void add_tablet(const tablet::pointer &p_tablet);

		inline
		table::tablet_map::size_type remove_tablet(const tablet::pointer &tablet) {
			Guard<ReadWriteLock::WriteLock> guard(m_tablets_lock.write_lock());
			return m_tablets.erase(tablet->tablet_name());
		}

		template<typename Container>
		void list_tablet(Container &list) const {
			Guard<ReadWriteLock::ReadLock> guard(m_tablets_lock.read_lock());
			BOOST_FOREACH(const tablet_map::value_type &elem, m_tablets)
			{
				list.push_back(elem.second);
			}
		}

		// // 注意：！
		// // pred中最好不要有任何锁，否则很容易造成死锁！
		// template<typename Container, typename Pred>
		// void list_tablet_if(Container &list, Pred pred) const {
		// 	Guard<ReadWriteLock::ReadLock> guard(m_tablets_lock.read_lock());
		// 	BOOST_FOREACH(const tablet_map::value_type &elem, m_tablets)
		// 	{
		// 		if(pred(elem.second))
		// 		{
		// 			list.push_back(elem.second);
		// 		}
		// 	}
		// }

		// // 注意：！
		// // p中最好不要有任何锁，否则很容易造成死锁！
		// template<typename Proc>
		// void foreach(Proc p) const {
		// 	Guard<ReadWriteLock::ReadLock> guard(m_tablets_lock.read_lock());
		// 	BOOST_FOREACH(const tablet_map::value_type &elem, m_tablets)
		// 	{
		// 		p(elem.second);
		// 	}
		// }

		bool is_loaded(const std::string &p_tablet_name) const;

		uint32_t tablet_number() const {
			Guard<ReadWriteLock::ReadLock> guard(m_tablets_lock.read_lock());
			return static_cast<uint32_t>(m_tablets.size());
		}

		uint32_t memory_table_size() const {
			uint32_t size = 0;
			Guard<ReadWriteLock::ReadLock> guard(m_tablets_lock.read_lock());
			BOOST_FOREACH(const tablet_map::value_type &elem, m_tablets)
			{
				size += elem.second->memory_table_size();
			}
			return size;
		}

		std::string table_name () const {
			return m_table_name;
		}

	protected:
		table_schema::pointer get_schema() const;

	private:
		table(const table &);
		table &operator=(const table &);

	private:
		std::string m_table_name;

		mutable table_schema::weak_pointer m_schema;
		mutable FastLock m_schema_lock;

		tablet_map m_tablets;
		mutable ReadWriteLock m_tablets_lock;
	};

}      // namespace xbase

#endif	// _TABLE_HPP_
